<?php

namespace Mifan\Alist;

use GuzzleHttp\Exception\GuzzleException;
use Mifan\Alist\client\Instances;
use Mifan\Alist\client\Options;
use Psr\Http\Message\ResponseInterface;

class Client
{
    use Instances;

    /**
     * error message
     * @var string
     */
    private $error;
    /**
     * @var Options
     */
    private $options;

    /**
     * error message
     * @return string
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     * @var \GuzzleHttp\Client
     */
    private $client;

    /**
     * @var array
     */
    private $apis;

    /**
     * @var string
     */
    private $token;

    /**
     * set token
     *
     * @param string $token
     *
     * @return Client
     */
    public function setToken($token)
    {
        $this->token = $token;
        return $this;
    }

    /**
     * @var ResponseInterface
     */
    public $response;


    public function __construct(Options $options)
    {
        $this->options = $options;
        $this->apis = $options->getApis();
        $this->client = new \GuzzleHttp\Client($options->getHttpConfig());
    }

    /**
     * request
     *
     * @param array|string $api see \Mifan\Alist\client\Options::$apis
     * @param array        $data
     * @param array        $options
     *
     * @return array|false|mixed
     */
    public function request($api, array $data = [], array $options = [])
    {
        if (is_string($api)) {
            $api = str_replace('/', '_', $api);
            if (!isset($this->apis[$api])) {
                $this->error = 'api not found';
                return false;
            }
            $api = $this->apis[$api];
        }

        if ($api['isAuth'] || !empty($this->token)) {
            if (empty($this->token)) {
                $this->error = 'token is empty';
                return false;
            }
            $options['headers']['Authorization'] = $this->token;
        }

        if (strtolower($api['method']) === "post") {
            $options['json'] = $data;
        } else {
            $options['query'] = $data;
        }

        try {
            $hooks = $this->options->getHooks();
            foreach ($hooks['request_before'] as $hook) {
                $hook($api, $data, $options);
            }

            $this->response = $this->client->request($api['method'], $api['path'], $options);
            $result = $this->response->getBody()->getContents();

            foreach ($hooks['request_after'] as $hook) {
                $hook($this->response, $result);
            }

            $result = json_decode($result, true);
        } catch (GuzzleException $e) {
            $this->error = $e->getMessage();
            return false;
        }

        if (!isset($result['code']) || $result['code'] !== 200) {
            $this->error = $result['message'] ?? '请求失败';
            return false;
        }

        return $result['data'] ?? [];
    }


}